﻿using System;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;
using System.IO;
using System.Text.RegularExpressions;
using System.Drawing;

namespace DX9ToolManaged
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            txtCtrlFxEditor.Lexing.LexerLanguageMap["hlsl"] = "cpp";
            txtCtrlFxEditor.ConfigurationManager.CustomLocation = Environment.CurrentDirectory;
            txtCtrlFxEditor.ConfigurationManager.Language = "hlsl";

            OpenedFileFullPath = "";

            //propEffectVariables.

            devicePanel.OnCreateDevice += this.devicePanel_OnCreateDevice;
            devicePanel.OnRender += this.devicePanel_OnRender;
            devicePanel.Init(this);
        }

        private DX9MeshBufferManagedWrapper mesh = new DX9MeshBufferManagedWrapper();
        private string OpenedFileFullPath;
        private Dx9FxMaterialWrapper FxMaterial = new Dx9FxMaterialWrapper();
        private static String FileDlgFilter = "DX9 Effects(*.fx)|*.fx|All files|*.*";

        private void devicePanel_OnCreateDevice(object sender, DeviceEventArgs e)
        {
            mesh.CreateFromFile("../Data/Mesh/Berserker.emd");
        }

        private void devicePanel_OnRender(object sender, DeviceEventArgs e)
        {
            e.Device.SetupView();
            Dx9FxManager.Instance.UpdateSharedMatrices();

            if (FxMaterial.IsAvailable())
            {
                FxMaterial.UpdateNonSharedMatrices();

                uint PassCount = FxMaterial.Begin();
                for (uint i=0; i<PassCount; i++)
                {
                    FxMaterial.BeginPass(i);
                    
                    mesh.Render();

                    FxMaterial.EndPass();
                }
                FxMaterial.End();
            }
            else
            {
                mesh.Render();
            }
        }

        private void PreviewEffect()
        {
            if (OpenedFileFullPath == null)
                return;

            if (!FxMaterial.LoadEffectFromFile(OpenedFileFullPath))
            {
                String ErrorString = Dx9FxManager.Instance.GetLastErrorString();
                textOutput.Text = ErrorString;
            }
            else
            {
                textOutput.Text = "Effect built successfully.";
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog FileDlg = new OpenFileDialog();

            FileDlg.Filter = FileDlgFilter;

            if (FileDlg.ShowDialog() == DialogResult.OK)
            {
                OpenedFileFullPath = FileDlg.FileName;

                this.Text = "FX Editor - " + OpenedFileFullPath;

                // Read file content to text control
                StreamReader FileReader = new StreamReader(OpenedFileFullPath, System.Text.Encoding.ASCII);
                txtCtrlFxEditor.Text = "";
                txtCtrlFxEditor.Text = FileReader.ReadToEnd();
                FileReader.Close();

                PreviewEffect();
            }
        }

        private void SaveCurrentEffect()
        {
            if (OpenedFileFullPath != null)
            {
                StreamWriter FileWriter = new StreamWriter(OpenedFileFullPath);
                FileWriter.Write(txtCtrlFxEditor.Text);
                FileWriter.Flush();
                FileWriter.Close();
            }
            else
            {
                // TODO: Call 'save as' here
            }
        }

        private void buildToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveCurrentEffect();

            PreviewEffect();
        }

        private void TraceByErrorString(String ErrorString)
        {
            try
            {
                int end = ErrorString.IndexOf("):");
                if (end == -1) return;

                int begin = ErrorString.LastIndexOf("(", end);
                String lineNum = ErrorString.Substring(begin + 1, end - begin - 1);
                String[] strVal = lineNum.Split(',');

                int Ln = int.Parse(strVal[0]) - 1;
                int Col = int.Parse(strVal[1]);

                txtCtrlFxEditor.Selection.End = txtCtrlFxEditor.Selection.Start = txtCtrlFxEditor.FindColumn(Ln, 0) + Col - 1;
                txtCtrlFxEditor.Scrolling.ScrollToCaret();
                txtCtrlFxEditor.Focus();
            }
            catch
            {
                return;
            }

        }

        private void textOutput_DoubleClick(object sender, EventArgs e)
        {
            RichTextBox OutputCtrl = (RichTextBox)sender;

            int lineBegin = OutputCtrl.GetFirstCharIndexOfCurrentLine();
            int lineIndex = OutputCtrl.GetLineFromCharIndex(lineBegin);
            int lineLen = OutputCtrl.Lines[lineIndex].Length;

            String line = OutputCtrl.Text.Substring(lineBegin, lineLen);
            TraceByErrorString(line);

            //OutputCtrl.Select(lineBegin, lineEnd - lineBegin);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            SaveCurrentEffect();
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            // This will fixed unhandled exception when application exit with maximum window
            this.WindowState = FormWindowState.Normal;
        }
    }
}
